package com.cw.lang.redis.config;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

import com.cw.lang.redis.service.impl.RedisForGeoServiceImpl;
import com.cw.lang.redis.service.impl.RedisForHashServiceImpl;
import com.cw.lang.redis.service.impl.RedisForListServiceImpl;
import com.cw.lang.redis.service.impl.RedisForSetServiceImpl;
import com.cw.lang.redis.service.impl.RedisServerServiceImpl;
import com.cw.lang.redis.template.StringKeyRedisTemplate;
import com.cw.lang.redis.service.RedisForGeoService;
import com.cw.lang.redis.service.RedisForHashService;
import com.cw.lang.redis.service.RedisForListService;
import com.cw.lang.redis.service.RedisForSetService;
import com.cw.lang.redis.service.RedisForValueService;
import com.cw.lang.redis.service.RedisForZSetService;
import com.cw.lang.redis.service.RedisServerService;
import com.cw.lang.redis.service.RedisService;
import com.cw.lang.redis.service.impl.RedisForValueServiceImpl;
import com.cw.lang.redis.service.impl.RedisForZSetServiceImpl;
import com.cw.lang.redis.service.impl.RedisServiceImpl;

/**
 * @author chenw
 * @version $$Id: RedisConfiguration.java, v 0.1 2018/10/18 下午6:50 chenw Exp $$
 */
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfiguration {

    @Autowired
    private RedisProperties redisProperties;

    @Resource(name = "redisTemplate")
    private RedisTemplate redisTemplate;

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Bean("stringKeyRedisTemplate")
    @ConditionalOnProperty(prefix = "cw.redis", value = "string-key-template-enabled", havingValue = "true")
    public StringKeyRedisTemplate stringKeyRedisTemplate() {
        StringKeyRedisTemplate template = new StringKeyRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @SuppressWarnings("unchecked")
    @Bean
    public RedisService redisService() {
        RedisServiceImpl redisService = new RedisServiceImpl();
        redisService.setRedisForGeoService(redisForGeo());
        redisService.setRedisForHashService(redisForHash());
        redisService.setRedisForListService(redisForList());
        redisService.setRedisForSetService(redisForSet());
        redisService.setRedisForValueService(redisForValue());
        redisService.setRedisForZSetService(redisForZSet());
        redisService.setRedisProperties(redisProperties);
        redisService.setRedisTemplate(redisTemplate);
        redisService.setStringKeyRedisTemplate(
            redisProperties.isStringKeyTemplateEnabled() ? stringKeyRedisTemplate() : null);
        return redisService;
    }

    @SuppressWarnings("unchecked")
    @Bean
    public RedisForHashService redisForHash() {
        RedisForHashServiceImpl service = new RedisForHashServiceImpl();
        service.setRedisProperties(redisProperties);
        service.setRedisTemplate(redisTemplate);
        service.setStringKeyRedisTemplate(
            redisProperties.isStringKeyTemplateEnabled() ? stringKeyRedisTemplate() : null);
        return service;
    }

    @SuppressWarnings("unchecked")
    @Bean
    public RedisForSetService redisForSet() {
        RedisForSetServiceImpl service = new RedisForSetServiceImpl();
        service.setRedisProperties(redisProperties);
        service.setRedisTemplate(redisTemplate);
        service.setStringKeyRedisTemplate(
            redisProperties.isStringKeyTemplateEnabled() ? stringKeyRedisTemplate() : null);
        return service;
    }

    @SuppressWarnings("unchecked")
    @Bean
    public RedisForListService redisForList() {
        RedisForListServiceImpl service = new RedisForListServiceImpl();
        service.setRedisProperties(redisProperties);
        service.setRedisTemplate(redisTemplate);
        service.setStringKeyRedisTemplate(
            redisProperties.isStringKeyTemplateEnabled() ? stringKeyRedisTemplate() : null);
        return service;
    }

    @SuppressWarnings("unchecked")
    @Bean
    public RedisForGeoService redisForGeo() {
        RedisForGeoServiceImpl service = new RedisForGeoServiceImpl();
        service.setRedisProperties(redisProperties);
        service.setRedisTemplate(redisTemplate);
        service.setStringKeyRedisTemplate(
            redisProperties.isStringKeyTemplateEnabled() ? stringKeyRedisTemplate() : null);
        return service;
    }

    @SuppressWarnings("unchecked")
    @Bean
    public RedisForValueService redisForValue() {
        RedisForValueServiceImpl service = new RedisForValueServiceImpl();
        service.setRedisProperties(redisProperties);
        service.setRedisTemplate(redisTemplate);
        service.setStringKeyRedisTemplate(
            redisProperties.isStringKeyTemplateEnabled() ? stringKeyRedisTemplate() : null);
        return service;
    }

    @SuppressWarnings("unchecked")
    @Bean
    public RedisForZSetService redisForZSet() {
        RedisForZSetServiceImpl service = new RedisForZSetServiceImpl();
        service.setRedisProperties(redisProperties);
        service.setRedisTemplate(redisTemplate);
        service.setStringKeyRedisTemplate(
            redisProperties.isStringKeyTemplateEnabled() ? stringKeyRedisTemplate() : null);
        return service;
    }

    @SuppressWarnings("unchecked")
    @Bean
    public RedisServerService redisServerService() {
        RedisServerServiceImpl service = new RedisServerServiceImpl();
        service.setRedisProperties(redisProperties);
        service.setRedisTemplate(redisTemplate);
        service.setStringKeyRedisTemplate(
            redisProperties.isStringKeyTemplateEnabled() ? stringKeyRedisTemplate() : null);
        return service;
    }
}
